﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace miniCCR
{

    public class ThreadHandle
    {
        public delegate void DelegateMessage(Operation op);
        public event DelegateMessage _EventDelegateMessage;

        public void OnMessage(Operation op)
        {
            _EventDelegateMessage(op);
        }
    }




    public abstract class ccrMain
    {

        public static ccrMain I;

        public ccrMain()
        {
            I = this;
        }

        public abstract void Start();

        

        private static ManualResetEvent[] resetEvents = new ManualResetEvent[1];



        //Dictionary<uint, GObject> _GObjectList = new Dictionary<uint, GObject>();

        Dictionary<uint, ComDispatcher> _ComDispatcherList = new Dictionary<uint, ComDispatcher>();

        Dictionary<string, GComponent> _ProxyList = new Dictionary<string, GComponent>();

        //static int _CPU_Count = 4;

        //public Queues.BlockingQueue<Operation>[] _Queues = new Queues.BlockingQueue<Operation>[_CPU_Count];

        // 쓰레드 세이프 리스트 써야함

        //List<GComponent> _CMList = new List<GComponent>();


        //public GComponent CreateComponent()
        //{

        //}

        //public void AddComponent(GComponent cm)
        //{
        //    //cm.ThreadStart();
        //    _CMList.Add(cm);
        //}


        public T GetProxy<T>(GComponent from) where T : Proxy
        {
            T temp = _ProxyList[typeof(T).Name].GetProxy(from) as T;

            temp._ToID = from._Owner._ID;

            return temp;
        }

        public T GetProxy<T>(GComponent from,uint toID) where T : Proxy
        {
            T temp = _ProxyList[typeof(T).Name].GetProxy(from) as T;

            temp._ToID = toID;
            

            return temp;
        }


        public void AddDispatcher(uint comID,ComDispatcher disp)
        {
            disp.Init();

            _ComDispatcherList.Add(comID, disp);        




        }

        public ComDispatcher CreateDipatcher()
        {
            ComDispatcher disp = new ComDispatcher();
            
            disp.Init();


            return disp;
        }

        public void AddGObject(GObject g)
        {
            g.Init();


            lock (this)
            {

                foreach (var com in g._ComponentList.Values)
                {

                    if (_ProxyList.Keys.Contains(com.GetProxyName()) == false)
                    {
                        _ProxyList.Add(com.GetProxyName(), com);
                    }


                    if( _ComDispatcherList.Keys.Contains(com._ComID) == false)
                    {
                        AddDispatcher(com._ComID, new ComDispatcher());
                    }
                    
                    _ComDispatcherList[com._ComID].Add(com);
                    
                    Init op = new Init();
                    op._ToID = g._ID;
                    
                    _ComDispatcherList[com._ComID].Enqueue(op);

                }

                //_GObjectList.Add(g._ID, g);
            }

            




            
        }

        public virtual GComponent OnCreate(string comType)
        {
            return null;
        }

        
        //public void AddEventOperation(int id, Operation op)
        //{
        //    _Queues[id % _CPU_Count].Enqueue(op);
        //}

        public void Post(Operation op)
        {
            lock (this)
            {
                if (op._ToComID == 0)
                {
                    foreach (var d in _ComDispatcherList.Values)
                    {
                        d.Enqueue(op);
                    }
                }
                else
                {
                    _ComDispatcherList[op._ToComID].Enqueue(op);
                }
            }
            
        }

        public void Run()
        {

            //for (int i = 0; i < _CPU_Count; i++)
            //{
            //    _Queues[i] = new Queues.BlockingQueue<Operation>(100);

            //    ThreadPool.QueueUserWorkItem(workThread,i);
            //}


            Start();

            resetEvents[0] = new ManualResetEvent(false);

            WaitHandle.WaitAll(resetEvents);


        }
             

        //public void AddObject(GObject obj)
        //{
        //    _GObjectList.Add(obj._ID,obj);
        //}


        //public void Update(int elapsed)
        //{
        //    UpdateTick t = new UpdateTick();

        //    foreach (GObject obj in _GObjectList.Values)
        //    {
        //        obj.OnMessage(t);
        //    }
        //}

    }
}
